a tool for shared writing and social publishing
1import { z } from "zod";
2import { makeRoute } from "../lib";
3import type { Env } from "./route";
4import { getConstellationBacklinks } from "app/lish/[did]/[publication]/[rkey]/getPostPageData";
5import { getDocumentURL } from "app/lish/createPub/getPublicationURL";
6import {
7 normalizeDocumentRecord,
8 normalizePublicationRecord,
9} from "src/utils/normalizeRecords";
10
11export const get_document_interactions = makeRoute({
12 route: "get_document_interactions",
13 input: z.object({
14 document_uri: z.string(),
15 }),
16 handler: async (
17 { document_uri },
18 { supabase }: Pick<Env, "supabase">,
19 ) => {
20 let { data: document } = await supabase
21 .from("documents")
22 .select(
23 `
24 data,
25 uri,
26 comments_on_documents(*, bsky_profiles(*)),
27 document_mentions_in_bsky(*),
28 documents_in_publications(publications(*))
29 `,
30 )
31 .eq("uri", document_uri)
32 .limit(1)
33 .single();
34
35 if (!document) {
36 return { comments: [], quotesAndMentions: [], totalMentionsCount: 0 };
37 }
38
39 const normalizedData = normalizeDocumentRecord(
40 document.data,
41 document.uri,
42 );
43
44 const pub = document.documents_in_publications?.[0]?.publications;
45 const normalizedPubRecord = pub
46 ? normalizePublicationRecord(pub.record)
47 : null;
48
49 // Compute document URL for constellation lookup
50 let absoluteUrl = "";
51 if (normalizedData) {
52 const postUrl = getDocumentURL(
53 normalizedData,
54 document.uri,
55 normalizedPubRecord,
56 );
57 absoluteUrl = postUrl.startsWith("/")
58 ? `https://leaflet.pub${postUrl}`
59 : postUrl;
60 }
61
62 // Fetch constellation backlinks
63 const constellationBacklinks = absoluteUrl
64 ? await getConstellationBacklinks(absoluteUrl)
65 : [];
66
67 // Deduplicate constellation backlinks internally
68 const uniqueBacklinks = Array.from(
69 new Map(constellationBacklinks.map((b) => [b.uri, b])).values(),
70 );
71
72 // Combine DB mentions and constellation backlinks, deduplicating by URI
73 const dbMentionUris = new Set(
74 document.document_mentions_in_bsky.map((m) => m.uri),
75 );
76 const quotesAndMentions: { uri: string; link?: string }[] = [
77 ...document.document_mentions_in_bsky.map((m) => ({
78 uri: m.uri,
79 link: m.link,
80 })),
81 ...uniqueBacklinks.filter((b) => !dbMentionUris.has(b.uri)),
82 ];
83
84 return {
85 comments: document.comments_on_documents,
86 quotesAndMentions,
87 totalMentionsCount: quotesAndMentions.length,
88 };
89 },
90});